
export class Control{
    container:HTMLElement;
    originX:number = 0;
    originY:number = 0;
    width:number = 0;
    height:number = 0;
    curpoint:any;
    radius:number = 6;
    points:HTMLElement[] = [];
    menu:HTMLElement = document.createElement('div');
    constructor(containerId:string, options?:object){
        let _this = this;
        let container = document.getElementById(containerId);
        if(!container) throw Error('Can not found Element by ID paramater as "'+containerId+'", in constructor of "Control"');
        _this.container = container;
        _this.menu.className = 'control-menu control-menu-hide';
        _this.menu.innerHTML = `<button class="control-menu-item" name="add" type="button">添加控制点</button>
        <button class="control-menu-item" name="remove" type="button">删除控制点</button>
        <button class="control-menu-item" name="clear" type="button">清空控制点</button>`;
        _this.menu.style.position = 'fixed';
        _this.container.appendChild(_this.menu);
        Object.assign(_this, options);
        _this.container.addEventListener('mousedown', downFn, {passive: false});
        document.addEventListener('mousemove', moveFn, {passive: false});
        document.addEventListener('mouseup', endFn, {passive: false});
        let left = 0, top = 0, startX = 0, startY = 0, target:any, index:number, menuTarget:any;
        function downFn(e:MouseEvent){
            e.preventDefault();
            target = e.target;
            index = _this.points.indexOf(target);
            if(index >= 0){
                _this.curpoint = target;
                startX = target.offsetLeft - e.clientX;
                startY = target.offsetTop - e.clientY;
            } else {
                switch(target && target.name){
                    case 'add':
                        _this.addPoint([e.clientX, e.clientY]);
                        _this.onadd(e.clientX, e.clientY);
                        break;
                    case 'remove':
                        if(menuTarget){
                            index = _this.points.indexOf(menuTarget);
                            if(index >= 0){
                                _this.removePoint(menuTarget);
                                _this.onremove(index*2);
                            }
                            menuTarget = null;
                        }
                        break;
                    case 'clear':
                        _this.clearPoints();
                        _this.onclear();
                }
            }
            _this.menu.classList.add('control-menu-hide');

        }
        function moveFn(e:MouseEvent){
            if(_this.curpoint){
                e.preventDefault();
                left = startX + e.clientX;
                top = startY + e.clientY;
                _this.curpoint.style.left = left + 'px';
                _this.curpoint.style.top = top + 'px';
                _this.onPointMove(index*2, index*2+1, left + _this.radius - _this.originX*2, top + _this.radius);
            }
        }
        function endFn(){
            _this.curpoint = null;
        }
        _this.container.oncontextmenu = menuFn;
        function menuFn(e:MouseEvent){
            e.preventDefault();
            _this.menu.classList.remove('control-menu-hide');
            _this.menu.style.left = e.clientX + 'px';
            _this.menu.style.top = e.clientY + 'px';
            menuTarget = e.target;
        }
    }
    init(points:number[]){
        this.clearPoints();
        this.addPoint(points);
    }
    pointXToLeft(pointX:number){
        return Math.round(pointX + this.originX - this.radius);
    }
    pointYToTop(pointY:number){
        return Math.round(this.height - pointY - this.originY - this.radius);
    }
    addPoint(points:number[]){
        let div:HTMLElement, frag = document.createDocumentFragment(), _this = this;
        for(let i=0; points[i] !== undefined && points[i+1] !== undefined; i+=2){
            div = document.createElement('div');
            div.style.position = 'absolute';
            div.style.left = _this.pointXToLeft(points[i]) + 'px';
            div.style.top = _this.pointYToTop(points[i+1]) + 'px';
            div.style.width = _this.radius*2 + 'px';
            div.style.height = _this.radius*2 + 'px';
            div.style.borderRadius = '50%';
            div.style.background = 'rgba(10,10,220, .6)';
            _this.points.push(div);
            frag.appendChild(div);
        }
        _this.container.appendChild(frag);
    }
    removePoint(point:HTMLElement){
        try{
            for(let len = this.points.length; len--;){
                if(point === this.points[len]) {
                    this.container.removeChild(point);
                    this.points.splice(len, 1);
                    break;
                }
            }
        }catch(err){}
    }
    clearPoints(){
        let len = this.points.length, i = 0;
        for(; i < len; i++){
            this.container.removeChild(this.points[i]);
        }
        this.points.splice(0, len);
    }
    onPointMove(index1:number, index2:number, x:number, y:number){}
    onadd(x:number, y:number){}
    onremove(index:number){}
    onclear(){}
}